package com.gqh.weather.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gqh.weather.config.FileConfig;
import com.gqh.weather.config.MinioConfig;
import com.gqh.weather.domain.dto.StudentTicketDTO;
import com.gqh.weather.domain.dto.TaskSchedule;
import com.gqh.weather.domain.entity.PcSubtask;
import com.gqh.weather.domain.entity.Task;
import com.gqh.weather.mapper.StudentMapper;
import com.gqh.weather.util.MinioUtil;

import io.minio.MinioClient;
import io.minio.PutObjectArgs;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;

/**
 * 答题卡生成服务类
 */
@Slf4j
@Service
public class AnswerSheetService {
    
//    @Autowired
//    private StudentMapper studentMapper;
//
//    @Autowired
//    private FileConfig fileConfig;
//
//    @Autowired
//    private MinioConfig minioConfig;
//
//    @Autowired
//    private MinioUtil minioUtil;
//
//    @Autowired
//    private MinioClient minioClient;
//
//    @Autowired
//    private RedisTemplate<String, String> redisTemplate;
//
//    // 用于JSON解析
//    private static final ObjectMapper objectMapper = new ObjectMapper();
//
//    /**
//     * 异步生成答题卡
//     *
//     * @param id PC子任务ID
//     * @param taskService 任务服务实例
//     * @param pcSubtaskService PC子任务服务实例
//     */
//    public void genAnswerSheetAsync(Integer id, TaskService taskService, PcSubtaskService pcSubtaskService) {
//        // 实现异步生成答题卡逻辑
//        // 这里应该参考Go代码中的go p.GenAnswerSheet(id)实现
//        log.info("异步生成答题卡，ID: {}", id);
//
//        // 创建一个新线程来异步生成答题卡
//        new Thread(() -> {
//            try {
//                genAnswerSheet(id, taskService, pcSubtaskService);
//            } catch (Exception e) {
//                log.error("生成答题卡失败: {}", e.getMessage(), e);
//            }
//        }).start();
//    }
//
//    /**
//     * 生成答题卡
//     *
//     * @param id PC子任务ID
//     * @param taskService 任务服务实例
//     * @param pcSubtaskService PC子任务服务实例
//     */
//    private void genAnswerSheet(Integer id, TaskService taskService, PcSubtaskService pcSubtaskService) {
//        try {
//            // 写入Redis状态 - 正在生成
//            saveGenState(id, 1, "正在生成答题卡");
//
//            // 获取PC子任务信息
//            PcSubtask pcSubtask = pcSubtaskService.getById(id);
//            if (pcSubtask == null) {
//                saveGenState(id, 3, "PC子任务不存在");
//                return;
//            }
//
//            // 获取关联的任务信息
//            Task task = taskService.getById(pcSubtask.getTaskPid());
//            if (task == null) {
//                saveGenState(id, 3, "关联的任务不存在");
//                return;
//            }
//
//            // 获取学生准考证信息
//            List<StudentTicketDTO> students = studentMapper.selectStudentTicketList(task.getId());
//            if (students.isEmpty()) {
//                saveGenState(id, 2, "该任务没有待考学生");
//                return;
//            }
//
//            // 验证学生信息
//            for (StudentTicketDTO student : students) {
//                if (student.getSchoolName() == null || student.getSchoolName().isEmpty()) {
//                    saveGenState(id, 3, "未找到学生对应的学校");
//                    return;
//                }
//                if (student.getCityName() == null || student.getCityName().isEmpty()) {
//                    saveGenState(id, 3, "未找到学校对应的区域");
//                    return;
//                }
//            }
//
//            // 创建导出目录
//            String exportDirPath = createExportDir(id, pcSubtaskService) + "answer_sheets/";
//            Path exportDir = Paths.get(exportDirPath);
//            if (!Files.exists(exportDir)) {
//                Files.createDirectories(exportDir);
//            }
//
//            // 生成答题卡ZIP文件
//            String zipFilePath = generateAnswerSheetZip(id, students, exportDirPath, task, pcSubtask);
//
//            if (zipFilePath != null) {
//                // 上传到MinIO
//                String fileUrl = uploadFile(zipFilePath);
//                if (fileUrl != null) {
//                    // 更新PC子任务的答题卡URL
//                    pcSubtask.setAnswerSheetUrl(fileUrl);
//                    pcSubtaskService.updateById(pcSubtask);
//
//                    // 写入Redis状态 - 成功，包含文件URL
//                    saveGenState(id, 0, null, fileUrl);
//                } else {
//                    saveGenState(id, 3, "上传文件失败");
//                }
//            } else {
//                saveGenState(id, 3, "生成答题卡失败");
//            }
//        } catch (Exception e) {
//            log.error("生成答题卡失败，ID: {}", id, e);
//            saveGenState(id, 3, "生成答题卡异常: " + e.getMessage());
//        }
//    }
//
//    /**
//     * 创建导出目录
//     *
//     * @param pcSubtaskId PC子任务ID
//     * @param pcSubtaskService PC子任务服务实例
//     * @return 导出目录路径
//     */
//    private String createExportDir(Integer pcSubtaskId, PcSubtaskService pcSubtaskService) {
//        try {
//            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
//            String exportDirPath = fileConfig.getExportDir() + "/export/" + pcSubtaskId + "_" + timestamp + "/";
//
//            // 创建目录
//            Path exportDir = Paths.get(exportDirPath);
//            if (!Files.exists(exportDir)) {
//                Files.createDirectories(exportDir);
//            }
//
//            // 创建图片目录
//            Path pictureDir = Paths.get(exportDirPath + "picture/");
//            if (!Files.exists(pictureDir)) {
//                Files.createDirectories(pictureDir);
//            }
//
//            return exportDirPath;
//        } catch (Exception e) {
//            log.error("创建导出目录失败: {}", e.getMessage(), e);
//            return null;
//        }
//    }
//
//    /**
//     * 生成答题卡ZIP文件
//     *
//     * @param id PC子任务ID
//     * @param students 学生列表
//     * @param exportDirPath 导出目录路径
//     * @param task 任务信息
//     * @param pcSubtask PC子任务信息
//     * @return ZIP文件路径
//     */
//    private String generateAnswerSheetZip(Integer id, List<StudentTicketDTO> students, String exportDirPath, Task task, PcSubtask pcSubtask) {
//        try {
//            // 从schedule字段中解析pdf_url
//            String basePdfUrl = parsePdfUrlFromSchedule(pcSubtask.getSchedule());
//
//            // 创建ZIP文件
//            String zipFileName = "答题卡exam_" + id + ".zip";
//            String zipFilePath = exportDirPath + zipFileName;
//
//            try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
//                // 为每个学生生成答题卡
//                for (StudentTicketDTO student : students) {
//                    // 生成学生答题卡PDF
//                    String pdfFileName = student.getStudentNo() + ".pdf";
//                    String pdfFilePath = exportDirPath + pdfFileName;
//
//                    // 生成带二维码的答题卡PDF
//                    generateStudentAnswerSheetPdf(pdfFilePath, student, basePdfUrl);
//
//                    // 添加PDF文件到ZIP，按照指定的目录结构
//                    String schoolName = student.getSchoolName() != null ? student.getSchoolName() : "未知学校";
//                    String cityName = student.getCityName() != null ? student.getCityName() : "未知城市";
//
//                    String zipEntryName = "答题卡exam_" + id + "/" + cityName + "/" + schoolName + "/" + pdfFileName;
//
//                    zipOut.putNextEntry(new ZipEntry(zipEntryName));
//                    Files.copy(Paths.get(pdfFilePath), zipOut);
//                    zipOut.closeEntry();
//
//                    // 删除临时PDF文件
//                    Files.deleteIfExists(Paths.get(pdfFilePath));
//                }
//            }
//
//            return zipFilePath;
//        } catch (Exception e) {
//            log.error("生成答题卡ZIP文件失败: {}", e.getMessage(), e);
//            return null;
//        }
//    }
//
//    /**
//     * 从schedule字段中解析pdf_url
//     *
//     * @param schedule schedule字段内容
//     * @return pdf_url
//     */
//    private String parsePdfUrlFromSchedule(String schedule) {
//        try {
//            if (schedule != null && !schedule.isEmpty() && !schedule.equals("[]")) {
//                // 解析JSON数组
//                List<TaskSchedule> schedules = objectMapper.readValue(schedule,
//                        new TypeReference<List<TaskSchedule>>() {});
//
//                // 返回第一个schedule的pdf_url
//                if (!schedules.isEmpty()) {
//                    return schedules.get(0).getPdfUrl();
//                }
//            }
//        } catch (Exception e) {
//            log.error("解析schedule字段失败: {}", e.getMessage(), e);
//        }
//        return null;
//    }
//
//    /**
//     * 生成学生答题卡PDF（带二维码）
//     *
//     * @param filePath PDF文件路径
//     * @param student 学生信息
//     * @param basePdfUrl 基础PDF URL
//     */
//    private void generateStudentAnswerSheetPdf(String filePath, StudentTicketDTO student, String basePdfUrl) {
//        try {
//            PDDocument document;
//
//            // 如果提供了基础PDF URL，则从URL下载PDF作为基础
//            if (basePdfUrl != null && !basePdfUrl.isEmpty()) {
//                // 下载基础PDF
//                document = downloadPdfFromUrl(basePdfUrl);
//            } else {
//                // 否则创建新的PDF文档
//                document = new PDDocument();
//                PDPage page = new PDPage();
//                document.addPage(page);
//            }
//
//            // 获取第一页的尺寸作为参考（假设所有页面尺寸相同）
//            PDPage firstPage = document.getPage(0);
//            float pageWidth = firstPage.getMediaBox().getWidth();
//            float pageHeight = firstPage.getMediaBox().getHeight();
//
//            // 生成二维码内容
//            String qrContent = student.getStudentNo();
//
//            // 生成二维码图像
//            int qrSize = 90; // 与Go代码保持一致
//            BufferedImage qrImage = generateQRCodeImage(qrContent, qrSize, qrSize);
//
//            // 计算二维码位置 (右上角)
//            // X位置：页面宽度 - 二维码宽度 - 右边距
//            float qrX = pageWidth - qrSize - 60; // 距离右边50个点
//            // Y位置：页面高度 - 二维码高度 - 上边距
//            float qrY = pageHeight - qrSize - 40; // 距离顶部50个点
//
//            // 将图像添加到PDF中（每一页的右上角，带虚线框块结构）
//            addImageToPDF(document, student, qrImage, qrX, qrY);
//
//            // 保存文档
//            document.save(filePath);
//            document.close();
//        } catch (IOException | WriterException e) {
//            log.error("生成学生答题卡PDF失败: {}", filePath, e);
//        }
//    }
//
//    /**
//     * 从URL下载PDF文件
//     *
//     * @param url PDF文件URL
//     * @return PDDocument对象
//     * @throws IOException IO异常
//     */
//    private PDDocument downloadPdfFromUrl(String url) throws IOException {
//        try {
//            // 创建URL对象
//            java.net.URL pdfUrl = new java.net.URL(url);
//
//            // 打开连接并读取PDF内容
//            try (InputStream inputStream = pdfUrl.openStream()) {
//                return PDDocument.load(inputStream);
//            }
//        } catch (Exception e) {
//            log.error("从URL下载PDF失败: {}", url, e);
//            // 如果下载失败，返回一个新的空PDF文档
//            PDDocument document = new PDDocument();
//            document.addPage(new PDPage());
//            return document;
//        }
//    }
//
//    /**
//     * 生成二维码图像
//     *
//     * @param text 二维码内容
//     * @param width 宽度
//     * @param height 高度
//     * @return 二维码图像
//     * @throws WriterException 编码异常
//     */
//    private BufferedImage generateQRCodeImage(String text, int width, int height) throws WriterException {
//        QRCodeWriter qrCodeWriter = new QRCodeWriter();
//        Map<EncodeHintType, Object> hints = new HashMap<>();
//        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
//        // 禁用默认边距，使二维码图像填满整个区域
//        hints.put(EncodeHintType.MARGIN, 0);
//        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
//        return MatrixToImageWriter.toBufferedImage(bitMatrix);
//    }
//
//    /**
//     * 将图像添加到PDF文档中（带虚线框块结构）
//     *
//     * @param document PDF文档
//     * @param student 学生信息
//     * @param image 图像
//     * @param x X坐标
//     * @param y Y坐标
//     * @throws IOException IO异常
//     */
//    private void addImageToPDF(PDDocument document, StudentTicketDTO student, BufferedImage image, float x, float y) throws IOException {
//        // 确保Y坐标不为负数
//        if (y < 0) {
//            y = 10; // 设置最小Y坐标
//        }
//
//        // 在每一页上添加块结构
//        for (int i = 0; i < document.getNumberOfPages(); i++) {
//            // 获取当前页
//            PDPage page = document.getPage(i);
//            float pageHeight = page.getMediaBox().getHeight();
//
//            // 计算文本位置（在二维码下方）
//            float nameY = y - 7; // 姓名在二维码下方5点
//            float studentNoY = nameY - 11; // 学号在姓名下方15点
//
//            // 创建内容流并清空虚线框内的区域，然后绘制虚线框（包裹二维码、姓名和学号）
//            try (PDPageContentStream contentStream = new PDPageContentStream(document, page,
//                    PDPageContentStream.AppendMode.APPEND, true)) {
//                // 先清空虚线框内的区域
//                float blockWidth = image.getWidth() + 12;  // 宽度为二维码宽度 + 边距
//                float blockHeight = image.getHeight() + 27; // 高度为二维码高度 + 姓名和学号空间 + 边距
//                float blockX = x - 5; // X位置向左偏移以居中
//                float blockY = y + image.getWidth() + 5; // Y位置向上偏移以包含所有内容
//
//                // 绘制白色矩形清空区域
//                contentStream.setNonStrokingColor(new PDColor(new float[]{1.0f, 1.0f, 1.0f}, PDDeviceRGB.INSTANCE));
//                contentStream.addRect(blockX, blockY - blockHeight, blockWidth, blockHeight);
//                contentStream.fill();
//
//                // 重置颜色为黑色
//                contentStream.setNonStrokingColor(new PDColor(new float[]{0.0f, 0.0f, 0.0f}, PDDeviceRGB.INSTANCE));
//
//                // 设置虚线模式
//                contentStream.setLineDashPattern(new float[]{3, 3}, 0);
//                contentStream.setLineWidth(1);
//
//                // 绘制虚线框 (包裹二维码、姓名和学号)
//                contentStream.moveTo(blockX, blockY);
//                contentStream.lineTo(blockX + blockWidth, blockY);
//                contentStream.lineTo(blockX + blockWidth, blockY - blockHeight);
//                contentStream.lineTo(blockX, blockY - blockHeight);
//                contentStream.lineTo(blockX, blockY);
//                contentStream.stroke();
//            }
//
//            // 添加二维码图像
//            try (PDPageContentStream imageStream = new PDPageContentStream(document, page,
//                    PDPageContentStream.AppendMode.APPEND, true)) {
//                // 将BufferedImage转换为PDImageXObject
//                ByteArrayOutputStream baos = new ByteArrayOutputStream();
//                ImageIO.write(image, "png", baos);
//                baos.flush();
//                byte[] imageBytes = baos.toByteArray();
//                baos.close();
//
//                // 创建PDImageXObject
//                org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject pdImage =
//                    org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.createFromByteArray(document, imageBytes, "qr_code");
//
//                imageStream.drawImage(pdImage, x, y, image.getWidth(), image.getHeight());
//            }
//
//            // 添加姓名和学号文本（在虚线框内）
//            try (PDPageContentStream textStream = new PDPageContentStream(document, page,
//                    PDPageContentStream.AppendMode.APPEND, true)) {
//                // 加载中文字体
//                PDFont chineseFont = null;
//                try {
//                    // 从resources/fonts目录加载字体文件
//                    chineseFont = PDType0Font.load(document, getClass().getResourceAsStream("/fonts/simhei.ttf"));
//                } catch (Exception e) {
//                    log.warn("加载中文字体失败，使用默认字体: {}", e.getMessage());
//                    // 如果字体加载失败，回退到默认字体
//                    chineseFont = PDType1Font.HELVETICA;
//                }
//
//                textStream.setFont(chineseFont, 8);
//                textStream.beginText();
//
//                // 添加姓名 (在二维码下方)
//                textStream.newLineAtOffset(x, nameY);
//                showTextSafely(textStream, student.getName(), chineseFont, 8.0f);
//                textStream.endText();
//
//                // 添加学号 (在姓名下方)
//                textStream.beginText();
//                textStream.newLineAtOffset(x, studentNoY);
//                showTextSafely(textStream, student.getStudentNo(), chineseFont, 8.0f);
//                textStream.endText();
//            }
//        }
//    }
//
//    /**
//     * 检查字符是否被字体支持
//     *
//     * @param c 字符
//     * @param font 字体
//     * @return 是否支持
//     */
//    private boolean isCharacterSupported(char c, PDFont font) {
//        try {
//            // 对于常见的ASCII字符，直接返回true以提高性能
//            if (c >= 32 && c <= 126) {
//                return true;
//            }
//            // 对于中文字符范围，直接返回true（黑体应该支持）
//            if (c >= 0x4E00 && c <= 0x9FFF) {
//                return true;
//            }
//            // 对于Unicode字符，尝试编码
//            font.encode(Character.toString(c));
//            return true;
//        } catch (Exception e) {
//            return false;
//        }
//    }
//
//    /**
//     * 安全地显示文本，避免不支持的字符导致异常
//     *
//     * @param contentStream 内容流
//     * @param text 文本内容
//     * @param font 字体
//     * @param fontSize 字体大小
//     * @throws IOException IO异常
//     */
//    private void showTextSafely(PDPageContentStream contentStream, String text, PDFont font, float fontSize) throws IOException {
//        try {
//            // 直接使用原始文本，不进行编码转换
//            contentStream.setFont(font, fontSize);
//            contentStream.showText(text);
//        } catch (Exception e) {
//            // 如果遇到任何异常，包括编码问题，过滤掉这些字符
//            StringBuilder filteredText = new StringBuilder();
//            for (char c : text.toCharArray()) {
//                try {
//                    // 检查字符是否可以被字体显示
//                    if (isCharacterSupported(c, font)) {
//                        filteredText.append(c);
//                    } else {
//                        // 如果字符不能被编码，替换为星号
//                        filteredText.append("*");
//                    }
//                } catch (Exception ex) {
//                    // 如果检查过程中出现异常，替换为星号
//                    filteredText.append("*");
//                }
//            }
//            contentStream.showText(filteredText.toString());
//        }
//    }
//
//    /**
//     * 上传文件
//     *
//     * @param filePath 文件路径
//     * @return 文件URL
//     */
//    private String uploadFile(String filePath) {
//        try {
//            File file = new File(filePath);
//            String objectName = "exam_packages/" + file.getName();
//
//            // 上传到MinIO
//            // 使用MinioClient直接上传文件
//            try (FileInputStream fis = new FileInputStream(file)) {
//                minioClient.putObject(
//                    PutObjectArgs.builder()
//                        .bucket(minioConfig.getBucketStudentFace())
//                        .object(objectName)
//                        .stream(fis, file.length(), -1)
//                        .contentType("application/octet-stream")
//                        .build()
//                );
//            }
//
//            // 返回文件URL
//            return "/files/" + minioConfig.getBucketStudentFace() + "/" + objectName;
//        } catch (Exception e) {
//            log.error("上传文件失败: {}", e.getMessage(), e);
//            return null;
//        }
//    }
//
//    /**
//     * 保存生成状态到Redis
//     *
//     * @param id PC子任务ID
//     * @param code 状态码
//     * @param msg 消息
//     */
//    private void saveGenState(Integer id, int code, String msg) {
//        saveGenState(id, code, msg, null);
//    }
//
//    /**
//     * 保存生成状态到Redis
//     *
//     * @param id PC子任务ID
//     * @param code 状态码
//     * @param msg 消息
//     * @param url 文件URL（仅在成功时提供）
//     */
//    private void saveGenState(Integer id, int code, String msg, String url) {
//        try {
//            Map<String, Object> state = new HashMap<>();
//            state.put("code", code);
//            if (msg != null) {
//                state.put("msg", msg);
//            }
//            // 成功时添加URL字段
//            if (code == 0 && url != null) {
//                state.put("url", url);
//            }
//
//            String stateJson = objectMapper.writeValueAsString(state);
//            String key = "gen_answer_sheet:task_" + id;
//            redisTemplate.opsForValue().set(key, stateJson);
//
//            log.info("保存生成状态到Redis，ID: {}, Code: {}, Msg: {}, URL: {}", id, code, msg, url);
//        } catch (Exception e) {
//            log.error("保存生成状态到Redis失败: {}", e.getMessage(), e);
//        }
//    }
}